import { ApiController, ApiPost, ApiGet, ApiBody, ApiBodyParam, DataType, Request } from 'xl-ts-plugins/router'
import { getRepository } from 'xl-ts-plugins/typeorm'
import { User, UserGender } from '../entity/User'
import TokenUserMidware from '../midware/token-user-midware'
import { mergeValidator, blankStringValidator, phoneValidator, lengthValidator, hasChineseValidator } from '../utils/validator'
import { ajaxResultFail, ajaxResultSuccess, ajaxLogFail } from '../utils/custom-result'

/**
 * 用户控制器
*/
@ApiController(
  { path: '/user', tags: ['User'] }
)
export default class UserController {

  @ApiPost({ path: '/register', summary: '注册' })
  async register(@ApiBody({ type: DataType.Model('User') }) user: User) {
    const errMsg = mergeValidator([{
      handler: blankStringValidator(user.userName),
      errorMsg: '请输入用户名'
    }, {
      handler: !lengthValidator(user.userName, { min: 3, max: 30 }),
      errorMsg: '用户名长度需为3-30'
    }, {
      handler: blankStringValidator(user.userPassword),
      errorMsg: '请输入密码'
    }, {
      handler: !lengthValidator(user.userPassword, { min: 3, max: 30 }),
      errorMsg: '密码长度需为3-30'
    }, {
      handler: hasChineseValidator(user.userPassword),
      errorMsg: '密码不能由中文组成'
    }, {
      handler: !phoneValidator(user.userPhone),
      errorMsg: '请输入正确的手机号'
    }, {
      handler: !(user.userGender in UserGender),
      errorMsg: '请输入正确的性别类型'
    }])

    if (errMsg) {
      return ajaxResultFail(errMsg)
    }

    try {
      const insertResult = await getRepository(User).insert(user)

      if (insertResult) {
        const insertUser = await getRepository(User).findOne(insertResult.raw.insertId)

        const {token, tokenData} = await TokenUserMidware.createToken(insertUser)

        await TokenUserMidware.saveTokenUser(token, tokenData)

        return ajaxResultSuccess(token, '注册成功')
      }
    } catch (error) {
      const errorMsg = error.toString() as string

      if (errorMsg.includes('UNIQUE_NAME')) {
        return ajaxResultFail('用户名已被注册')
      } else if (errorMsg.includes('UNIQUE_PHONE')) {
        return ajaxResultFail('手机号已被注册')
      } else {
        return ajaxLogFail(error)
      }
    }
  }


  @ApiPost({ path: '/login', summary: '登录' })
  async login(
    @ApiBodyParam({ name: 'userName', type: DataType.String, description: '用户名' }) userName,
    @ApiBodyParam({ name: 'password', type: DataType.String, description: '密码' }) password
  ) {
    const errMsg = mergeValidator([{
      handler: blankStringValidator(userName),
      errorMsg: '请输入用户名'
    }, {
      handler: blankStringValidator(password),
      errorMsg: '请输入密码'
    }, {
      handler: !lengthValidator(password, { min: 3, max: 30 }),
      errorMsg: '密码长度需为3-30'
    }])

    if (errMsg) {
      return ajaxResultFail(errMsg)
    }

    const findUser = await getRepository(User).findOne({
      userName,
      userPassword: password
    })

    if (findUser) {
      const {token, tokenData} = await TokenUserMidware.createToken(findUser)

      await TokenUserMidware.saveTokenUser(token, tokenData)

      return ajaxResultSuccess(token)
    } else {
      return ajaxResultFail('用户不存在或密码错误')
    }
  }


  @ApiGet({ path: '/logout', summary: '退出登录' }, TokenUserMidware.midware)
  async logout(@Request req) {
    const tokenUser = TokenUserMidware.getTokenData(req)

    if (tokenUser) {
      TokenUserMidware.removeAllTokenUser(tokenUser)

      return ajaxResultSuccess('退出登录成功')
    } else {
      return ajaxResultFail('找不到该用户')
    }
  }


  @ApiGet({
    path: '/getUserInfo', summary: '获取用户信息',
    responseModel: { type: DataType.Model('User') }
  }, TokenUserMidware.midware)
  async getUserInfo(@Request req) {
    const tokenUser = TokenUserMidware.getTokenData(req)

    if (tokenUser) {
      return ajaxResultSuccess(tokenUser)
    } else {
      return ajaxResultFail('找不到该用户')
    }
  }


  @ApiPost({ path: '/modifyUser', summary: '修改用户' }, TokenUserMidware.midware)
  async modifyUser(@Request req, @ApiBody({ type: DataType.Model('User') }) updateUser: User) {
    const validatorList = []

    updateUser.userName && validatorList.push({
      handler: !lengthValidator(updateUser.userName, { min: 3, max: 30 }),
      errorMsg: '用户名长度需为3-30'
    })

    updateUser.userPhone && validatorList.push({
      handler: !phoneValidator(updateUser.userPhone),
      errorMsg: '请输入正确的手机号'
    })

    updateUser.userGender && validatorList.push({
      handler: !(updateUser.userGender in UserGender),
      errorMsg: '请输入正确的性别类型'
    })

    const errMsg = mergeValidator(validatorList)

    if (errMsg) {
      return ajaxResultFail(errMsg)
    }

    const tokenUser = TokenUserMidware.getTokenData(req)
    const token = await TokenUserMidware.getToken(req)

    // 修改对象设为 token user
    updateUser.userId = tokenUser.userId
    // 禁止修改密码
    delete updateUser.userPassword
    // 禁止修改状态
    delete updateUser.userStatus

    if (tokenUser) {

      try {
        const result = await getRepository(User).save(updateUser)

        if (result) {
          // 先同步设置当前的 token 保存到 redis 的 user
          await TokenUserMidware.updateTokenUser(token, result)
          // 再异步设置其它的 token
          TokenUserMidware.updateAllTokenUser(result)

          return ajaxResultSuccess('修改成功')
        }
      } catch (error) {
        const errorMsg = error.toString() as string

        if (errorMsg.includes('UNIQUE_NAME')) {
          return ajaxResultFail('用户名已被注册')
        } else if (errorMsg.includes('UNIQUE_PHONE')) {
          return ajaxResultFail('手机号已被注册')
        } else {
          return ajaxLogFail(error)
        }
      }
    } else {
      return ajaxResultFail('找不到该用户')
    }
  }

}